<template>
  <div class="table-container" style="display: flex; flex-flow: column">
    <vxe-modal v-model="modalVisible"
               :esc-closable="true"
               :duration="0"
               title="自定义列"
               width="50%"
               :position="{ top: '15%', left: 'center' }"
               height="50%"
               auto-resize
               show-footer
               transfer>
      <template v-slot>
        <vxe-table round
                   stripe
                   ref="columnTable"
                   resizable
                   auto-resize
                   header-align="center"
                   align="center"
                   show-overflow
                   height="auto"
                   @checkbox-change="onCheckBoxChange"
                   :data="columnData"
                   v-bind="$attrs"
                   v-on="$listeners"
                   :mouse-config="{selected: true}"
                   :keyboard-config="{isArrow: true, isDel: true, isEnter: true, isTab: true, isEdit: true, isClip: true}"
                   :checkbox-config="{trigger: 'cell', checkField: 'visible'}"
                   :edit-config="{trigger: 'dblclick', mode: 'cell', selected: true}">
          <vxe-table-column type="checkbox" width="60" align="center"></vxe-table-column>
          <vxe-table-column type="seq" title="序号" width="60" align="center"></vxe-table-column>
          <vxe-table-column field="field" title="字段"></vxe-table-column>
          <vxe-table-column field="title" title="标题"></vxe-table-column>
          <vxe-table-column field="width" title="宽度" :edit-render="{name: 'input', autoselect: true}"></vxe-table-column>
          <vxe-table-column field="align" title="标题水平方向" :edit-render="{name: 'select', autoselect:true}">
            <template v-slot="{ row, index }">
              <vxe-select v-model="row.headerAlign" transfer :size="size">
                <vxe-option value="left" label="左对齐"></vxe-option>
                <vxe-option value="center" label="居中"></vxe-option>
                <vxe-option value="right" label="右对齐"></vxe-option>
              </vxe-select>
            </template>
          </vxe-table-column>
          <vxe-table-column field="align" title="内容水平方向">
            <template v-slot="{ row, index }">
              <vxe-select v-model="row.align" transfer :size="size">
                <vxe-option value="left" label="左对齐"></vxe-option>
                <vxe-option value="center" label="居中"></vxe-option>
                <vxe-option value="right" label="右对齐"></vxe-option>
              </vxe-select>
            </template>
          </vxe-table-column>
          <vxe-table-column field="fixed" title="固定列">
            <template v-slot="{ row, index }">
              <vxe-select v-model="row.fixed" transfer :size="size">
                <vxe-option value="left" label="左固定"></vxe-option>
                <vxe-option value="" label="不固定"></vxe-option>
                <vxe-option value="right" label="右固定"></vxe-option>
              </vxe-select>
            </template>
          </vxe-table-column>
          <vxe-table-column field="sortable" title="允许排序">
            <template v-slot="{ row, index }">
              <vxe-switch v-model="row.sortable" on-label="是" off-label="否"></vxe-switch>
            </template>
          </vxe-table-column>
        </vxe-table>
      </template>
      <template v-slot:footer>
        <div class="button-container" style="text-align: right;">
          <vxe-button type="button" status="primary" @click="saveColumn">保存设置</vxe-button>
          <vxe-button type="button" @click="handleResetColumn">还原设置</vxe-button>
        </div>
      </template>
    </vxe-modal>

    <div class="table-content" style="flex: 1;">
      <vxe-grid
          class="custom-grid"
          ref="xGrid"
          :key="key"
          border
          :data="data"
          auto-resize
          resizable
          row-class-name="custom-grid-row"
          cell-class-name="custom-grid-cell"
          show-overflow
          show-header-overflow
          show-footer-overflow
          height="auto"
          highlight-current-row
          highlight-hover-column
          highlight-hover-row
          row-id="id"
          header-align="center"
          align="center"
          :round="false"
          :keyboard-config="{isArrow: true, isEnter: true, isTab: true, isClip: true}"
          :sort-config="{ showIcon: false }"
          :radio-config="{ labelField: 'seq', trigger: 'row' }"
          :seq-config="{startIndex: (query.pageNum - 1) * query.pageSize}"
          @context-menu-click="contextMenuClickEvent"
          @header-cell-click="headerCellClickEvent"
          v-bind="$attrs"
          v-on="$listeners"
          style="display: flex; flex-flow: column">
        <template v-slot:top>
          <vxe-toolbar v-if="perfect && buttons.length" :perfect="perfect">
            <template v-slot:buttons>
              <vxe-button v-for="(btn, key) in defaultButtons"
                          :type="btn.type"
                          :key="key"
                          status="perfect"
                          v-if="!btn.hidden"
                          @click="btnClick(btn)">
                <svg-icon v-if="btn.icon" :icon-class="btn.icon"/>
                <span style="margin-left: 5px">{{ btn.name }}</span>
              </vxe-button>
            </template>
            <template v-slot:tools>
              <slot name="tools"/>
            </template>
          </vxe-toolbar>
          <vxe-toolbar v-else-if="!perfect && buttons.length">
            <template v-slot:buttons>
              <Button v-for="(btn, key) in defaultButtons"
                      class="mr10"
                      :type="btn.status"
                      :key="key"
                      :size="size"
                      v-if="!btn.hidden"
                      @click="btnClick(btn)">
                <svg-icon v-if="btn.icon" :icon-class="btn.icon"/>
                <span style="margin-left: 5px">{{ btn.name }}</span>
              </Button>
            </template>
            <template v-slot:tools>
              <slot name="tools"/>
            </template>
          </vxe-toolbar>
        </template>
        <template v-slot:form>
          <div class="tool-bar-container">
            <slot name="form"></slot>
          </div>
        </template>
        <template v-slot:pager>
          <vxe-pager perfect
                     class="table-footer"
                     style="text-align: center;"
                     :current-page.sync="query.pageNum"
                     :page-size.sync="query.pageSize"
                     :total.sync="query.total"
                     :page-sizes="[10, 20, 50, 100, 500, 1000]"
                     :layouts="['PrevPage', 'JumpNumber', 'NextPage', 'FullJump', 'Sizes', 'Total']"
                     @page-change="handlePageChange"/>
        </template>
      </vxe-grid>
    </div>
  </div>
</template>

<script>
import { checkPermit, checkRole } from "@/utils/permission"; // 权限判断函数
import { getGridOptions, getUserGridOptions, updateUserGridOptions } from "@/api/business/table";
import { parseStrEmpty } from '../../utils'

export default {
  name: 'GridTable',
  props: {
    size: {
      type: String,
      default: 'medium'
    },
    name: {
      type: String,
      default: ''
    },
    buttons: {
      type: Array,
      default: () => { return [] }
    },
    query: {
      type: Object,
      default: () => {
        return {
          pageNum: 1,
          pageSize: 20
        }
      }
    },
    perfect: {
      type: Boolean,
      default: true
    },
    data: {
      type: Array,
      default: () => { return [] }
    },
    remoteMethod: {
      type: Function,
      default: (query) => {}
    },
    refForm: {
      type: String,
      default: ''
    },
    tableId: {
      type: Number,
      default: 0
    },
    slotColumn: {
      type: Object,
      default: null
    },
  },
  data() {
    return {
      key: 1,
      loaded: true,
      modalVisible: false,
      columnData: [],
      rowData: [],
      defaultButtons: {
        add: { name: '新增', icon: 'add', status: 'primary', permit: '*', hidden: true },
        edit: { name: '编辑', icon: 'edit', status: 'edit',  permit: '*', hidden: true },
        delete: { name: '删除', icon: 'trash', status: 'error', permit: '*', hidden: true },
        search: { name: '查询', icon: 'search', status: 'success', click: this.handleRefresh, permit: '*', hidden: true },
        import: { name: '导入', icon: 'import', permit: '*', hidden: true },
        export: { name: '导出', icon: 'export', permit: '*', hidden: true },
        reset: { name: '重置', icon: 'reset', click: this.handleReset, permit: '*', hidden: true },
        setting: { name: '设置', icon: 'setting', click: this.handleCustomColumn, permit: '*', hidden: true }
      },
    }
  },
  created() {
    for (let i = 0; i < this.buttons.length; i++) {
      // 判断是否为自定义按钮
      if (!this.defaultButtons[this.buttons[i].type]) {
        this.defaultButtons[this.buttons[i].type] = this.buttons[i]
        continue
      }
      if (this.buttons[i].click) {
        this.defaultButtons[this.buttons[i].type].click = this.buttons[i].click
      }
      if (!this.buttons[i].hidden) {
        this.defaultButtons[this.buttons[i].type].hidden = false
      }
      this.defaultButtons[this.buttons[i].type].permit = this.buttons[i].permit
    }
    if (this.tableId) {
      // 动态加载列配置
      getGridOptions(this.tableId).then(res => {
        console.log(JSON.parse(res.data.gridOptions))
        const ownOptions = parseStrEmpty(res.data.gridOptions) === "" ? {} : JSON.parse(res.data.gridOptions);
        const parentOptions = JSON.parse(res.data.parentOptions);
        const gridOptions = Object.assign(parentOptions, ownOptions);
        const $grid = this.$refs.xGrid;
        if (this.slotColumn) {
          for (let i = 0; i < gridOptions.columns.length; i++) {
            console.log(this.slotColumn, gridOptions.columns[i])
            if (this.slotColumn.hasOwnProperty(gridOptions.columns[i].field)) {
              gridOptions.columns[i].slots = this.slotColumn[gridOptions.columns[i].field]
            }
          }
        }
        const tableColumns = $grid.getTableColumn().fullColumn
        gridOptions.columns = gridOptions.columns.concat(tableColumns)
        // 初始化标准模板的配置
        $grid.loadColumn(gridOptions.columns);
        getUserGridOptions(this.$store.getters.user.userId, this.tableId).then(res => {
          if (!res.data) return
          const userGridOptions = parseStrEmpty(res.data.gridOptions) !== "" ? JSON.parse(res.data.gridOptions) : {}
          const columns = []
          if (userGridOptions) {
            for (let i = 0; i < userGridOptions.length; i++) {
              let tableColumn = $grid.getColumnByField(userGridOptions[i].field)
              if (tableColumn) {
                tableColumn = Object.assign(tableColumn, userGridOptions[i])
                columns.push(tableColumn)
              } else if (tableColumns[i].type === 'seq' || tableColumns[i].type === 'radio' ||
                tableColumns[i].type === 'checkbox') {
                columns.push(Object.assign(tableColumns[i], userGridOptions[i]))
              }
            }
            // 初始化用户自定义模板配置
            $grid.reloadColumn(columns);
            $grid.refreshColumn()
          }
        })
      })
    } else if (this.slotColumn) {
      this.$nextTick(() => {
        const $grid = this.$refs.xGrid;
        const columns = $grid.getTableColumn().fullColumn
        for (let i = 0; i < columns.length; i++) {
          console.log(this.slotColumn, columns[i])
          if (this.slotColumn.hasOwnProperty(columns[i].field || columns[i].property)) {
            columns[i].slots = this.slotColumn[columns[i].field || columns[i].property]
          }
        }
        $grid.reloadColumn(columns);
        $grid.refreshColumn()
      })
    }
  },
  methods: {
    checkPermit,
    checkRole,
    btnClick(btn) {
      if (btn.click && btn.click instanceof Function) {
        btn.click();
      } else {
        window.alert("暂不支持" + btn.name + "操作");
      }
    },
    onCheckBoxChange({ records, reserves, indeterminates, checked, row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event  }) {
      // const tableColumn = this.$refs.xGrid.getColumnByField(row.field) || this.$refs.xGrid.getColumnById(row._XID)
      // if (tableColumn) {
      //   if (tableColumn.visible !== row.visible) {
      //     if (row.visible) {
      //       this.$refs.xGrid.showColumn(tableColumn)
      //     } else{
      //       this.$refs.xGrid.hideColumn(tableColumn)
      //     }
      //   }
      // }
    },
    saveColumn() {
      const rows = this.$refs.columnTable.getData()
      const $grid = this.$refs.xGrid
      const columns = []
      const tableColumns = $grid.getTableColumn().fullColumn
      if (rows) {
        for (let i = 0; i < rows.length; i++) {
          let tableColumn = $grid.getColumnByField(rows[i].field)
          if (tableColumn) {
            tableColumn = Object.assign(tableColumn, rows[i])
            columns.push(tableColumn)
          } else {
            delete rows[i].field
            columns.push(Object.assign(tableColumns[i], rows[i]))
          }
        }
        $grid.reloadColumn(columns)
        $grid.refreshColumn()
        const configString = JSON.stringify(rows)
        updateUserGridOptions(this.$store.getters.user.userId, this.tableId, configString).then(res => {
          this.$notify({
            title: 'success',
            type: 'success',
            message: '保存成功',
            duration: 2000
          })
        })
      }
      this.modalVisible = false
    },
    headerCellClickEvent ({ column, triggerResizable, triggerSort, triggerFilter }) {
      // 如果触发了列的其他功能按钮
      if (column.sortable && !(triggerResizable || triggerSort || triggerFilter)) {
        if (column.order === 'desc') {
          this.$refs.xGrid.clearSort()
        } else if (column.order === 'asc') {
          this.$refs.xGrid.sort(column.property, 'desc')
        } else {
          this.$refs.xGrid.sort(column.property, 'asc')
        }
      }
    },
    handleResetColumn() {
      this.$XModal.confirm('是否还原列设置为初始状态？', '重置提示', {
        mask: false,
        transfer: true
      })
          .then(type => {
            if (type === 'confirm') {
              const $grid = this.$refs.xGrid
              this.$nextTick(() => {
                getGridOptions(this.tableId).then(res => {
                  const ownOptions = parseStrEmpty(res.data.gridOptions) === "" ? {} : JSON.parse(res.data.gridOptions);
                  const parentOptions = JSON.parse(res.data.parentOptions);
                  const gridOptions = Object.assign(parentOptions, ownOptions);
                  const $grid = this.$refs.xGrid;
                  if (this.slotColumn) {
                    for (let i = 0; i < gridOptions.columns.length; i++) {
                      if (this.slotColumn.hasOwnProperty(gridOptions.columns[i].field)) {
                        gridOptions.columns[i].slots = this.slotColumn[gridOptions.columns[i].field]
                      }
                    }
                  }
                  // 初始化标准模板的配置
                  $grid.reloadColumn(gridOptions.columns)
                  $grid.refreshColumn()

                  this.$nextTick(() => {
                    const tableColumn = $grid.getTableColumn().fullColumn
                    this.columnData = []
                    for (let i = 0; i < tableColumn.length; i++) {
                      this.columnData.push({
                        type: tableColumn[i].type,
                        field: tableColumn[i].property,
                        title: tableColumn[i].title,
                        width: tableColumn[i].width || tableColumn[i].renderWidth,
                        align: tableColumn[i].align || "center",
                        sortable: tableColumn[i].sortable,
                        fixed: tableColumn[i].fixed,
                        visible: tableColumn[i].visible,
                        headerAlign: tableColumn[i].headerAlign || "center"
                      })
                    }
                    const configString = JSON.stringify(this.columnData)
                    console.log(configString)
                    updateUserGridOptions(this.$store.getters.user.userId, this.tableId, configString).then(res => {
                      this.$notify({
                        title: 'success',
                        type: 'success',
                        message: '重置成功',
                        duration: 2000
                      })
                    })
                  })
                })
              })
              // this.$refs.xGrid.resetColumn({
              //   visible: true,
              //   resizable: true
              // })
              // this.$refs.xGrid.reloadData(this.tableData)
              // this.handleCustomColumn()
              this.modalVisible = false
            }
          })
    },
    handleCustomColumn() {
      const tableColumn = this.$refs.xGrid.getTableColumn().fullColumn
      this.columnData = []
      for (let i = 0; i < tableColumn.length; i++) {
        this.columnData.push({
          type: tableColumn[i].type,
          field: tableColumn[i].property,
          title: tableColumn[i].title,
          width: tableColumn[i].renderWidth || tableColumn[i].width,
          align: tableColumn[i].align,
          sortable: tableColumn[i].sortable,
          fixed: tableColumn[i].fixed,
          visible: tableColumn[i].visible,
          headerAlign: tableColumn[i].headerAlign || "center"
        })
      }
      this.modalVisible = true
      return this.columnData
      // 保存用户列配置到服务器
    },
    contextMenuClickEvent({ menu, row, column }) {
      let xGrid = this.$refs.xGrid
      switch (menu.code) {
        case 'zoom':
          xGrid.zoom()
          break
      }
    },
    handleReset() {
      this.$parent.$refs[this.refForm].reset();
    },
    handleRefresh() {
      this.query.pageNum = 1;
      this.handleRemoteMethod(this.query);
    },
    handlePageChange({type, currentPage, pageSize, $event}) {
      // this.page.size = pageSize
      // this.$emit('update:page', {current: currentPage, size: pageSize}, this.page.total)
      this.query.pageNum = currentPage
      this.query.pageSize = pageSize
      this.handleRemoteMethod(this.query)
    },
    async handleRemoteMethod(query) {
      await new Promise((resolve, reject) => {
        this.$emit('remote-method', query, resolve)
      })
    },
    getCurrentRow() {
      return this.$refs.xGrid.getCurrentRecord()
    },
    removeCurrentRow() {
      return this.$refs.xGrid.removeCurrentRow()
    },
    readFile(options) {
      return this.$refs.xGrid.readFile(options)
    }
  }
}
</script>

<style>
  .tool-bar-container {
    margin-top: 10px;
  }
  .vxe-button {
    outline: none;
  }
  /*滚动条整体部分*/
  .custom-grid div::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  /*滚动条的轨道*/
  .custom-grid div::-webkit-scrollbar-track {
    background-color: #FFFFFF;
  }
  /*滚动条里面的小方块，能向上向下移动*/
  .custom-grid div::-webkit-scrollbar-thumb {
    background-color: #ccc;
    border-radius: 5px;
    border: 1px solid #F1F1F1;
    box-shadow: inset 0 0 6px rgba(0,0,0,.2);
  }
  .custom-grid div::-webkit-scrollbar-thumb:hover {
    background-color: #A8A8A8;
  }
  .custom-grid div::-webkit-scrollbar-thumb:active {
    background-color: #787878;
  }
  /*边角，即两个滚动条的交汇处*/
  .custom-grid div::-webkit-scrollbar-corner {
    background-color: #FFFFFF;
  }
  .custom-grid-row {
    height: 64px;
  }
  .custom-grid-cell {
    height: 64px;
  }
</style>
